package com.aiobc.file.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.aiobc.file.config.FileUploadConfig;
import com.aiobc.file.dto.FileUploadResp;
import com.aiobc.file.enums.FileEnum;
import com.aiobc.file.enums.RespCodeEnum;
import com.aiobc.file.exceptions.FileUploadException;
import com.aiobc.file.service.FileService;
import com.aiobc.file.service.MinioTemplate;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.List;

/**
 * @author fengzh
 * @className FileServiceImpl
 * @date 2020/4/22 18:33
 */
@Slf4j
@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private FileUploadConfig fileUploadConfig;

    // private static final String BUCKET_NAME = "smart-park";

    @Autowired
    private MinioTemplate minioTemplate;

    @Override
    public FileUploadResp uploadSingle(MultipartFile file) {
        checkFile(file);
        return upload(file);
    }

    @Override
    public List<FileUploadResp> uploadBatch(MultipartFile[] files) {
        checkBatchFile(files);
        List<FileUploadResp> fileUploadRespList = Lists.newArrayList();
        for (MultipartFile file : files) {
            FileUploadResp fileUploadResp = upload(file);
            fileUploadRespList.add(fileUploadResp);
        }

        return fileUploadRespList;
    }

    @Override
    public void downLoad(HttpServletResponse response, String fileName) {
        try (InputStream inputStream = minioTemplate.getObject(fileUploadConfig.getBucketName(), fileName)) {
            response.setContentType("application/octet-stream; charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
            // response.setContentType("application/force-download");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
            IoUtil.copy(inputStream, response.getOutputStream());
        } catch (Exception e) {
            log.error("文件读取异常", e);
        }
    }

    private FileUploadResp upload(MultipartFile file) {
        String fileName = IdUtil.simpleUUID() + StrUtil.DOT
                + cn.hutool.core.io.FileUtil.extName(file.getOriginalFilename());

        // 上传文件
        try {
            minioTemplate.putObject(fileUploadConfig.getBucketName(), fileName, file.getInputStream());
        } catch (Exception e) {
            log.error("文件上传失败:", e);
            throw new FileUploadException(RespCodeEnum.FAIL);

        }
        // 获取文件路径
        String fileUrl = fileUploadConfig.getUrl() + StrUtil.SLASH + fileUploadConfig.getBucketName() + StrUtil.SLASH + fileName;
        // String fileUrl = minioTemplate.getObjectURL(BUCKET_NAME, fileName,
        // FILE_EXPIRE_TIME);
        // 抽取前面的图片路径, 问号后面的参数去掉，否则无法访问
        // fileUrl = fileUrl.substring(0, fileUrl.indexOf("?"));

        return new FileUploadResp(fileUrl, fileName, file.getOriginalFilename());
    }

    private void checkFile(MultipartFile file) {
        // 处理上传文件
        if (file == null) {
            throw new FileUploadException(RespCodeEnum.NULL);
        }

        String oriName = file.getOriginalFilename();
        FileEnum mediaType = getFileFormat(oriName);
        if (mediaType == null) {
            log.error("格式错误, 文件名称:{}", oriName);
            throw new FileUploadException(RespCodeEnum.ERROR_FORMAT);
        }

        Long length = file.getSize();// 设置上传图片
        log.info("文件上传大小为:{}", length);
        if (mediaType.isImage() && length > fileUploadConfig.getImageLimit()) {
            throw new FileUploadException(RespCodeEnum.EXCEED_LIMIT);
        }

        if (mediaType.isWord() && length > fileUploadConfig.getWordLimit()) {
            throw new FileUploadException(RespCodeEnum.EXCEED_LIMIT);
        }
    }

    private void checkBatchFile(MultipartFile[] files) {
        if (files == null || files.length == 0) {
            throw new FileUploadException(RespCodeEnum.NULL);
        }

        for (MultipartFile file : files) {
            checkFile(file);
        }
    }
    /**
     * 获取文件类型是否是视频类型 0->图片 1->视频 -1->非法
     *
     * @param name
     * @return
     */
    public static FileEnum getFileFormat(String name) {
        String ext = name;
        if (!StringUtils.isEmpty(name) && name.contains(".")) {
            ext = name.substring(name.lastIndexOf(".")).trim().toLowerCase();
        }

        return FileEnum.parse(ext);
    }

}
